package czk.concrent.protectpause;



import java.io.IOException;
import java.util.*;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/5/25 22:56
 */
public class Test1 {
    public static void main(String[] args) {
        // 线程一等待线程二的下载结果
        GuardedObject guardedObject=new GuardedObject(1);
        new Thread(()->{
            // 等待结果
            System.out.println("等待结果");
            List pause = (ArrayList)guardedObject.pause(2*1000);
            if(pause!=null){
                System.out.println(pause.size());
            }
        },"t1").start();
        new Thread(()->{
        try {
            List<String> download = new DownLoader().download();
            guardedObject.change(download);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    },"t2").start();

    }
}
class GuardedObject{
    // 定义id
    private int id;

    public GuardedObject(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    //
    private Object object;
    // wait暂停
    // 现在时间
    public Object pause(long time){
        long startTime = System.currentTimeMillis();
        long passedTime=0l;
        while (object==null){
            if (passedTime>time){
                System.out.println(Thread.currentThread().getName()+"不想等了");
                break;
            }
            synchronized (this){
                try {
                    // 考虑虚假唤醒后，只需要等time-passedTime
                    this.wait(time-passedTime);
                    System.out.println(Thread.currentThread().getName()+"我被唤醒了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 计算等待时间
                passedTime=System.currentTimeMillis()-startTime;
            }
        }
        return object;
    }
    // 赋值
    public void change(Object object){
        synchronized (this){
            this.object=object;
            // 唤醒
            this.notifyAll();
            System.out.println("唤醒他");
        }
    }

}
// 邮箱类
// 存放多个guardedObject
class MailBoxes{
    // 创建集合
    private static Map<Integer,GuardedObject> map=new Hashtable<>();
    private static int id=1;
    // 产生位移id
    public synchronized static int generateId(){
        return id++;
    }
    // 创建对象，增加编号
    public  static  GuardedObject createGuardedObject(){
        GuardedObject guardedObject= new GuardedObject(generateId());
        map.put(guardedObject.getId(),guardedObject);
        return guardedObject;
    }
    // 获取所有id
    public synchronized static Set<Integer> getIds(){
        return map.keySet();
    }
    // 获得GuardedObject
    public static GuardedObject getGuardedObject(int id){
        return map.remove(id);
    }
}
// 居民类
class People extends Thread{
    @Override
    public  void run() {
        GuardedObject guardedObject = MailBoxes.createGuardedObject();
        System.out.println(Thread.currentThread().getName()+"收信前"+guardedObject.getId());
        Object mail = guardedObject.pause(5 * 1000);
        System.out.println(Thread.currentThread().getName()+"收到信件"+mail);
    }
}
// 邮递员类
class PostMan extends Thread{
    // id
    private int id;
    // 邮箱信息
    private String mail;
    // 构造方法
    public PostMan(int id,String mail){
        this.id=id;
        this.mail=mail;
    }

    @Override
    public  void run() {
        System.out.println(Thread.currentThread().getName()+"开始送信 id="+id);
        GuardedObject guardedObject = MailBoxes.getGuardedObject(id);
        guardedObject.change(mail);
        System.out.println(Thread.currentThread().getName()+"送信完成");
    }
}
class TestImprove{
    public static void main(String[] args) throws InterruptedException {
        // 开始收信
        for (int i = 0; i < 3; i++) {
            new People().start();
        }
        Thread.sleep(2*1000);
        Set<Integer> ids = MailBoxes.getIds();
        for (Integer id : ids) {
            System.out.println(id);
        }

        // 开始送信
        for (Integer id : MailBoxes.getIds()) {
            new PostMan(id,"送信"+id).start();
        }
    }
}
